package tjs.study.notes.dotest.jdk.thread;

import tjs.study.notes.base.common.TestBuiUtils;

import java.util.concurrent.atomic.AtomicMarkableReference;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * Created by Nicky.Tang on 2021/11/15 10:34 下午
 *
 * @since 02.12.10
 */
public class DoTestOfCAS {
    private final static AtomicMarkableReference<Long> amr = new AtomicMarkableReference<>(new Long(0), false);
    private final static AtomicStampedReference<Long> asr = new AtomicStampedReference<>(new Long(0), 0);
    private final static AtomicReference<Long> ar = new AtomicReference<>(new Long(1));

    public static void main(String[] args) {
        new TestBuiUtils().desc("测试AtomicMarkableReference").times(10).functionTest((taskNum) -> {
            testMarkStamped();
            //testMarkBoolean();
        }).doTestThread();
    }

    private static void testMarkStamped() {
        Long nowVal = asr.getReference();
        int nowStamp = asr.getStamp();
        do {
            nowVal = asr.getReference();
            nowStamp = asr.getStamp();
            System.out.println("我是线程 " + Thread.currentThread().getId() + ",我没改成功 " + nowVal + " " + nowStamp);
        } while (!asr.compareAndSet(nowVal, nowVal + 1, nowStamp, nowStamp + 1));
        System.out.println("我是线程 " + Thread.currentThread().getId() + ",我改成功了 " + (nowVal + 1) + " " + (nowStamp + 1));
    }

    private static void testMarkBoolean() {
        Long nowVal = amr.getReference();
        boolean nowFlag = amr.isMarked();
        do {
            nowVal = amr.getReference();
            nowFlag = amr.isMarked();
            System.out.println("我是线程 " + Thread.currentThread().getId() + ",我没改成功 " + nowVal + " " + nowFlag);
        } while (!amr.compareAndSet(nowVal, nowVal + 1, nowFlag, !nowFlag));
        System.out.println("我是线程 " + Thread.currentThread().getId() + ",我改成功了 " + (nowVal + 1) + " " + !nowFlag);

        // 简化如下
//            while (true) {
//                if (amr.compareAndSet(amr.getReference(), amr.getReference() + "1", amr.isMarked(), !amr.isMarked())) {
//                    break;
//                }
//                Thread.currentThread().sleep(500);
//            }
    }

    private static void testReference() {
    }

}
